/*
 * @Descripttion:
 * @Author: jhw
 * @Date: 2024-04-25 09:44:46
 * @LastEditors: jhw
 * @LastEditTime: 2024-04-26 14:02:19
 */

import { vnode } from "./vnode";
import { sameVnode, createElement, createKeyToIndex } from "./utils";

/**
 *
 * @param {*} oldVnode 旧vnode sel, data, children, text, elm
 * @param {*} newVnode 新vnode sel, data, children, text, elm
 * @description 比较新旧vnode
 */
export function patch(oldVnode, newVnode) {
  console.log("*");
  // 判断oldVnode是否是虚拟节点
  if (oldVnode.sel === undefined) {
    // oldVnode是真实DOM
    oldVnode = vnode(
      oldVnode.tagName.toLowerCase(),
      {},
      [],
      undefined,
      oldVnode
    );
  }

  // 判断新旧vnode是否是同一个节点
  if (sameVnode(oldVnode, newVnode)) {
    // 新旧vnode是同一个节点
    // patchVnode(oldVnode, newVnode);
    console.log("新旧vnode是同一个节点");
    // 1.判断新旧是否一样
    if (oldVnode === newVnode) return;
    // 2.判断新vnode是否有text属性
    if (newVnode.text) {
      if (newVnode.text !== oldVnode.text) {
        oldVnode.elm.innerText = newVnode.text;
      }
    } else {
      // 3.判断旧vnode是否有children属性
      if (oldVnode.children === undefined || oldVnode.children.length === 0) {
        oldVnode.elm.innerText = "";
        oldVnode.elm.appendChild(createElement(newVnode));
      } else {
        console.log("新旧vnode都有children属性");
        // 4.新旧vnode都有children属性
        updateChildren(oldVnode.elm, oldVnode.children, newVnode.children);
      }
    }
    newVnode.elm = oldVnode.elm;
  } else {
    // 新旧vnode不是同一个节点
    console.log("新旧vnode不是同一个节点");
    // 创建新节点
    const newVnodeElm = createElement(newVnode);
    // 插入新节点
    if (oldVnode.elm.parentNode && newVnodeElm) {
      oldVnode.elm.parentNode.insertBefore(newVnodeElm, oldVnode.elm);
    }
    // 删除旧节点
    oldVnode.elm.parentNode.removeChild(oldVnode.elm);
  }
}

/**
 *
 * @param {*} oldVnode 旧vnode sel, data, children, text, elm
 * @param {*} newVnode 新vnode sel, data, children, text, elm
 * @description 更新子元素
 */
export function updateChildren(parentElm, oldCh, newCh) {
  console.log("更新子元素*", parentElm, oldCh, newCh);
  let oldStartIdx = 0;
  let oldEndIdx = oldCh.length - 1;
  let newStartIdx = 0;
  let newEndIdx = newCh.length - 1;
  let oldStartVnode = oldCh[0];
  let oldEndVnode = oldCh[oldEndIdx];
  let newStartVnode = newCh[0];
  let newEndVnode = newCh[newEndIdx];
  let keyMap = null;

  while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {
    if (oldStartVnode == undefined) {
      oldStartVnode = oldCh[++oldStartIdx];
    } else if (oldEndVnode == undefined) {
      oldEndVnode = oldCh[--oldEndIdx];
    } else if (newStartVnode == undefined) {
      newStartVnode = newCh[++newStartIdx];
    } else if (newEndVnode == undefined) {
      newEndVnode = newCh[--newEndIdx];
    } else if (sameVnode(oldStartVnode, newStartVnode)) {
      patch(oldStartVnode, newStartVnode);
      oldStartVnode = oldCh[++oldStartIdx];
      newStartVnode = newCh[++newStartIdx];
    } else if (sameVnode(oldEndVnode, newEndVnode)) {
      patch(oldEndVnode, newEndVnode);
      oldEndVnode = oldCh[--oldEndIdx];
      newEndVnode = newCh[--newEndIdx];
    } else if (sameVnode(oldStartVnode, newEndVnode)) {
      patch(oldStartVnode, newEndVnode);
      parentElm.insertBefore(oldStartVnode.elm, oldEndVnode.elm.nextSibling);
      oldStartVnode = oldCh[++oldStartIdx];
      newEndVnode = newCh[--newEndIdx];
    } else if (sameVnode(oldEndVnode, newStartVnode)) {
      patch(oldEndVnode, newStartVnode);
      parentElm.insertBefore(oldEndVnode.elm, oldStartVnode.elm);
      oldEndVnode = oldCh[--oldEndIdx];
      newStartVnode = newCh[++newStartIdx];
    } else {
      if (!keyMap) keyMap = createKeyToIndex(oldCh, oldStartIdx, oldEndIdx);

      const idxInOld = keyMap[newStartVnode.key];
      if (idxInOld === undefined) {
        // 如果是undefined，说明是新节点
        parentElm.insertBefore(createElement(newStartVnode), oldStartVnode.elm);
      } else {
        // 如果不是undefined，说明在旧节点中存在 只需要移动即可
        const elmToMove = oldCh[idxInOld];
        patch(elmToMove, newStartVnode);
        // 将旧节点置为undefined
        oldCh[idxInOld] = undefined;
        parentElm.insertBefore(elmToMove.elm, oldStartVnode.elm);
      }
      newStartVnode = newCh[++newStartIdx];
    }
  }

  if (oldStartIdx >= oldEndIdx) {
    // 旧节点已经遍历完，新节点还有剩余
    for (let i = newStartIdx; i <= newEndIdx; i++) {
      // const newNodeKey = newCh[newEndIdx + 1]
      //   ? newCh[newEndIdx + 1]["key"]
      //   : null;
      // const before = newNodeKey
      //   ? oldCh.find((item) => item.key === newNodeKey)
      //   : null;
      const before = newCh[newEndIdx + 1].elm ? newCh[newEndIdx + 1].elm : null;
      parentElm.insertBefore(createElement(newCh[i]), before);
    }
  }
  // 不能用else if 有可能新节点遍历完了 旧节点还有剩余
  if (newStartIdx >= newEndIdx) {
    // 新节点已经遍历完，旧节点还有剩余
    for (let i = oldStartIdx; i <= oldEndIdx; i++) {
      parentElm.removeChild(oldCh[i].elm);
    }
  }
}
